package com.crois.barrier.metrics.prometheus.service;

import com.crois.barrier.metrics.api.MetricsBootService;
import com.crois.barrier.metrics.config.MetricsConfig;
import com.crois.barrier.metrics.prometheus.collector.BuildInfoCollector;
import com.crois.barrier.metrics.prometheus.register.PrometheusMetricsRegister;
import com.crois.barrier.metrics.reporter.MetricsReporter;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.HTTPServer;
import io.prometheus.client.hotspot.DefaultExports;
import io.prometheus.jmx.JmxCollector;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.management.MalformedObjectNameException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Hou Ze Yu
 * @description
 * @date 2021/4/22
 */
@Slf4j
@Data
public class PrometheusMetricsBootService implements MetricsBootService {

    private HTTPServer server;

    private volatile AtomicBoolean registered = new AtomicBoolean(false);

    @Override
    public void start(MetricsConfig metricsConfig) {
        startServer(metricsConfig);
        MetricsReporter.register(PrometheusMetricsRegister.getInstance());
    }

    @Override
    public void stop() {
        if (server!=null) {
            server.stop();
            log.info("Prometheus metrics HTTP server stop  start success.");
        }
    }

    private void startServer(final MetricsConfig metricsConfig) {
        register(metricsConfig.getJmxConfig());
        Integer port = metricsConfig.getPort();
        String host = metricsConfig.getHost();
        InetSocketAddress inetSocketAddress;
        if (null == host || "".equalsIgnoreCase(host)) {
            inetSocketAddress = new InetSocketAddress(port);
        }else {
            inetSocketAddress = new InetSocketAddress(host,port);
        }
        try {
            server = new HTTPServer(inetSocketAddress, CollectorRegistry.defaultRegistry, true);
            log.info(String.format("Prometheus metrics HTTP server `%s:%s` start success.", inetSocketAddress.getHostString(), inetSocketAddress.getPort()));
        } catch (final IOException ex) {
            log.error("Prometheus metrics HTTP server start fail", ex);
        }
    }



    private void register(final String jmxConfig) {
         if (!registered.compareAndSet(false,true)) {
             log.info("---------------------------------");
             return;
         }
         new BuildInfoCollector().register();
             try {
                 if (!Objects.isNull(jmxConfig)) {
                   new JmxCollector(jmxConfig).register();
                 }
                 DefaultExports.initialize();
             } catch (MalformedObjectNameException e) {
                 log.error("init jmx collector error", e);
             }
    }
}
